
#include <Inklude/ikCXmlDomReader.h>

#define XERCES_STATIC_LIBRARY

#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/XMLString.hpp>


#include <iostream>

using namespace Inklude;
using namespace xercesc;
using namespace std;

ikCXmlDomReader::ikCXmlDomReader()
{
    _init();
}

ikCXmlDomReader::~ikCXmlDomReader()
{
    _destroy();
}

void ikCXmlDomReader::_init()
{
    try
    {
        XMLPlatformUtils::Initialize();
    }
    catch (const XMLException& toCatch)
    {
        char* message = XMLString::transcode(toCatch.getMessage());
        cout << "Error during initialization! :\n" << message << "\n";
        XMLString::release(&message);
    }

    m_pParser = new xercesc::XercesDOMParser();
    xercesc::XercesDOMParser* pParser = (xercesc::XercesDOMParser*)m_pParser;
    pParser->setValidationScheme(XercesDOMParser::Val_Always);
    pParser->setDoNamespaces(true);
    m_pErrorHandler = (ErrorHandler*) new HandlerBase();
    ErrorHandler* pErrHandler = (ErrorHandler*)m_pErrorHandler;
    pParser->setErrorHandler(pErrHandler);

}

void ikCXmlDomReader::_destroy()
{
}

void ikCXmlDomReader::Parse(const char* XmlFileName)
{
    xercesc::XercesDOMParser* pParser = (xercesc::XercesDOMParser*)m_pParser;
    pParser->parse(XmlFileName);
}

unsigned int ikCXmlDomReader::GetNumberOfTagElements(ikCString& TagName)
{
    unsigned int retVal = 0;
    DOMNodeList* pNodeList = (DOMNodeList*)(_getNodeList(TagName));
    if (NULL != pNodeList)
    {
        retVal = pNodeList->getLength();
    }
    return retVal;
}

void ikCXmlDomReader::for_each(ikCString& TagName, 
                               std::vector<ikCString> AttributesVec, 
                               std::function<void(std::vector<ikCString> )> func)
{
    DOMNodeList* pNodeList = (DOMNodeList*)(_getNodeList(TagName));
    if (NULL != pNodeList)
    {
        for (unsigned int i=0; i<pNodeList->getLength(); i++)
        {
            DOMNode* pNode = pNodeList->item(i);
            DOMNamedNodeMap* pAttrList = pNode->getAttributes();
            std::vector<ikCString> attrValueVec;

            for each (ikCString attrName in AttributesVec)
            {
                for (unsigned int j=0; j<pAttrList->getLength(); j++)
                {
                    DOMNode* pAttr = pAttrList->item(j);
                    if (ikCString(pAttr->getLocalName()) == attrName)
                    {
                        const XMLCh* value = pAttr->getNodeValue();
                        if (NULL != value)
                        {
                            ikCString attrValue = value;
                            attrValueVec.push_back(attrValue);
                        }
                    }
                }
            }

            if (AttributesVec.size() == attrValueVec.size())
            {
                func(attrValueVec);
            }
        }
    }
}

void ikCXmlDomReader::GetValue(ikCString& TagName, ikCString& AttributeName, ikCString& Value)
{
    DOMNodeList* pNodeList = (DOMNodeList*)(_getNodeList(TagName));
    if (NULL != pNodeList)
    {
        DOMNode* pNode = pNodeList->item(0);
        DOMNamedNodeMap* pAttrList = pNode->getAttributes();
        for (size_t i=0; i<pAttrList->getLength(); i++)
        {
            DOMNode* pAttr = pAttrList->item(i);
            if (ikCString(pAttr->getLocalName()) == AttributeName)
            {
                const XMLCh* value = pAttr->getNodeValue();
                if (NULL != value)
                {
                    Value = value;
                }
            }
        }
    }
}

void* ikCXmlDomReader::_getNodeList(ikCString& TagName)
{
    xercesc::XercesDOMParser* pParser = (xercesc::XercesDOMParser*)m_pParser;
    DOMDocument* pDoc = pParser->getDocument();
    DOMNodeList* pNodeList = pDoc->getElementsByTagName(TagName.c_wstr());
    return pNodeList;
}

void ikCXmlDomReader::GetValue(ikCString& TagName, ikCString& AttributeName, int& Value)
{
    ikCString val;
    GetValue(TagName, AttributeName, val);
    Value = val.ToInt();
}

void ikCXmlDomReader::GetValue(ikCString& TagName, ikCString& AttributeName, float& Value)
{
    ikCString val;
    GetValue(TagName, AttributeName, val);
    Value = val.ToFloat();
}
